const timeFieldExp = /^(?:\[[\d:.]+\])+/g;
const timeExp = /\d{1,3}(:\d{1,3}){0,2}(?:\.\d{1,3})/g;
const t_rxp_1 = /^0+(\d+)/;
const t_rxp_2 = /:0+(\d+)/g;
const t_rxp_3 = /\.0+(\d+)/;

const formatTimeLabel = (label: string) => {
  return label
    .replace(t_rxp_1, "$1")
    .replace(t_rxp_2, ":$1")
    .replace(t_rxp_3, ".$1");
};

export function parseLrc(lrcstr = "") {
  const lines = lrcstr.split(/\r\n|\n|\r/);
  const linesMap: Record<
    string,
    {
      time: number;
      text: string;
    }
  > = {};

  for (let line of lines) {
    line = line.trim();
    let result = timeFieldExp.exec(line);
    if (!result) continue;
    const timeField = result[0];
    const text = line.replace(timeFieldExp, "").trim();
    if (!text) continue;
    const times = timeField.match(timeExp);
    if (!times) continue;
    for (let time of times) {
      const timeStr = formatTimeLabel(time);
      const timeArr = timeStr.split(":");
      if (timeArr.length > 3) continue;
      else if (timeArr.length < 3)
        for (let i = 3 - timeArr.length; i--; ) timeArr.unshift("0");
      if (timeArr[2].includes("."))
        timeArr.splice(2, 1, ...timeArr[2].split("."));

      linesMap[timeStr] = {
        time:
          parseInt(timeArr[0]) * 60 * 60 * 1000 +
          parseInt(timeArr[1]) * 60 * 1000 +
          parseInt(timeArr[2]) * 1000 +
          parseInt(timeArr[3] || "0"),
        text,
      };
    }
  }
  return Object.values(linesMap).sort((a, b) => a.time - b.time);
}
